/**
 * This is for OpenApi SDK
 */

import './utils' OpenApiUtil;
import Credential;
import SPI;

@go("type Config = models.Config
type GlobalParameters = models.GlobalParameters
type Params = models.Params
type OpenApiRequest = models.OpenApiRequest
")

@pythonModel({
  header = "from ..utils_models import Params, Config, GlobalParameters, OpenApiRequest\n",
  exports = ["Params", "Config", "GlobalParameters", "OpenApiRequest"]
})

type @endpoint = string
type @regionId = string
type @protocol = string
type @method = string
type @userAgent = string
type @endpointRule = string
type @endpointMap = map[string]string
type @suffix = string
type @readTimeout = integer
type @connectTimeout = integer
type @httpProxy = string
type @httpsProxy = string
type @socks5Proxy = string
type @socks5NetWork = string
type @noProxy = string
type @network = string
type @productId = string
type @maxIdleConns = integer
type @endpointType = string
type @openPlatformEndpoint = string
type @credential = Credential
type @signatureVersion = string
type @signatureAlgorithm = string
type @headers = map[string]string
type @spi = SPI
type @globalParameters = OpenApiUtil.GlobalParameters
type @key = string
type @cert = string
type @ca = string
type @disableHttp2 = boolean
type @retryOptions = $RetryOptions
type @tlsMinVersion = string


model SSEResponse {
  headers: map[string]string,
  statusCode: number(description='HTTP Status Code'),
  event: $SSEEvent
}

exception AlibabaCloud extends $ResponseError {
  statusCode?: number(description='HTTP Status Code'),
  code?: string(description="Error Code"),
  message?: string(description="Error Message"),
  description?: string(description="Error Description"),
  requestId?: string(description="Request ID"),
}

exception Client extends AlibabaCloud {
  accessDeniedDetail?: map[string]any(description="Access Denied Detail"),
}

exception Server extends AlibabaCloud {
}

exception Throttling extends AlibabaCloud {
  retryAfter?: long(description="Retry After(ms)"),
}

/**
 * Init client with Config
 * @param config config contains the necessary information to create a client
 */
init(config: OpenApiUtil.Config) {
  if ($isNull(config)) {
    throw new Client {
      code = 'ParameterMissing',
      message = '\'config\' can not be unset'
    };
  }

  if((!$isNull(config.accessKeyId) && config.accessKeyId != "") && (!$isNull(config.accessKeySecret) && config.accessKeySecret != "")){
    if (!$isNull(config.securityToken) && config.securityToken != "") {
      config.type = 'sts';
    } else {
      config.type = 'access_key';
    }
    var credentialConfig = new Credential.Config{
      accessKeyId = config.accessKeyId,
      type = config.type,
      accessKeySecret = config.accessKeySecret
    };
    credentialConfig.securityToken = config.securityToken;
    @credential = new Credential(credentialConfig);
  } else if (!$isNull(config.bearerToken) && config.bearerToken != "") {
    var cc = new Credential.Config{
      type = 'bearer',
      bearerToken = config.bearerToken
    };
    @credential = new Credential(cc);
  } else if(!$isNull(config.credential)) {
    @credential = config.credential;
  }
  @endpoint = config.endpoint;
  @endpointType = config.endpointType;
  @network = config.network;
  @suffix = config.suffix;
  @protocol = config.protocol;
  @method = config.method;
  @regionId = config.regionId;
  @userAgent = config.userAgent;
  @readTimeout = config.readTimeout;
  @connectTimeout = config.connectTimeout;
  @httpProxy = config.httpProxy;
  @httpsProxy = config.httpsProxy;
  @noProxy = config.noProxy;
  @socks5Proxy = config.socks5Proxy;
  @socks5NetWork = config.socks5NetWork;
  @maxIdleConns = config.maxIdleConns;
  @signatureVersion = config.signatureVersion;
  @signatureAlgorithm = config.signatureAlgorithm;
  @globalParameters = config.globalParameters;
  @key = config.key;
  @cert = config.cert;
  @ca = config.ca;
  @disableHttp2 = config.disableHttp2;
  @retryOptions = config.retryOptions;
  @tlsMinVersion = config.tlsMinVersion;
}

/**
 * Encapsulate the request and invoke the network
 * @param action api name
 * @param version product version
 * @param protocol http or https
 * @param method e.g. GET
 * @param authType authorization type e.g. AK
 * @param bodyType response body type e.g. String
 * @param request object of OpenApiRequest
 * @param runtime which controls some details of call api, such as retry times
 * @return the response
 */
api doRPCRequest(action: string, version: string, protocol: string, method: string, authType: string, bodyType: string, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): object {
  __request.protocol = $string($default(@protocol, protocol));
  __request.method = method;
  __request.pathname = '/';
  var globalQueries : map[string]string = {};
  var globalHeaders : map[string]string = {};
  if (!$isNull(@globalParameters)) {
    var globalParams = @globalParameters;
    if (!$isNull(globalParams.queries)) {
      globalQueries = globalParams.queries;
    }
    if (!$isNull(globalParams.headers)) {
      globalHeaders = globalParams.headers;
    }
  }
  var extendsHeaders : map[string]string = {};
  var extendsQueries : map[string]string = {};
  if (!$isNull(runtime.extendsParameters)) {
    var extendsParameters = runtime.extendsParameters;
    if (!$isNull(extendsParameters.headers)) {
      extendsHeaders = extendsParameters.headers;
    }
    if (!$isNull(extendsParameters.queries)) {
      extendsQueries = extendsParameters.queries;
    }
  }
  __request.query = {
    Action = action,
    Format = 'json',
    Version = version,
    Timestamp = OpenApiUtil.getTimestamp(),
    SignatureNonce = OpenApiUtil.getNonce(),
    ...globalQueries,
    ...extendsQueries,
    ...request.query
  };

  var headers = getRpcHeaders();
  if($isNull(headers)){
    // endpoint is setted in product client
    __request.headers = {
      host = @endpoint,
      x-acs-version = version,
      x-acs-action = action,
      user-agent = OpenApiUtil.getUserAgent(@userAgent),
      ...globalHeaders,
      ...extendsHeaders,
      ...request.headers
    };
  } else {
    __request.headers = {
      host = @endpoint,
      x-acs-version = version,
      x-acs-action = action,
      user-agent = OpenApiUtil.getUserAgent(@userAgent),
      ...globalHeaders,
      ...extendsHeaders,
      ...request.headers,
      ...headers
    };
  }

  if (!$isNull(request.body)) {
    var m = $object(request.body);
    var tmp = $object(OpenApiUtil.query(m));
    __request.body = $Form.toFormString(tmp);
    __request.headers.content-type = 'application/x-www-form-urlencoded';
  }


  if (authType != 'Anonymous') {
    if ($isNull(@credential)) {
      throw new Client{
        code = `InvalidCredentials`,
        message = `Please set up the credentials correctly. If you are setting them through environment variables, please ensure that ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set correctly. See https://help.aliyun.com/zh/sdk/developer-reference/configure-the-alibaba-cloud-accesskey-environment-variable-on-linux-macos-and-windows-systems for more details.`
      }
    }
    var credentialModel = @credential.getCredential();
    if (!$isNull(credentialModel.providerName)) {
      __request.headers.x-acs-credentials-provider = credentialModel.providerName;
    }
    var credentialType = credentialModel.type;
    if (credentialType == 'bearer') {
      var bearerToken = credentialModel.bearerToken;
      __request.query.BearerToken = bearerToken;
      __request.query.SignatureType = 'BEARERTOKEN';
    } else {
      var accessKeyId = credentialModel.accessKeyId;
      var accessKeySecret = credentialModel.accessKeySecret;
      var securityToken = credentialModel.securityToken;
      if (!$isNull(securityToken) && securityToken != "") {
        __request.query.SecurityToken = securityToken;
      }
      __request.query.SignatureMethod = 'HMAC-SHA1';
      __request.query.SignatureVersion = '1.0';
      __request.query.AccessKeyId = accessKeyId;
      var t : map[string]any = null;
      if (!$isNull(request.body)) {
        t = $object(request.body);
      }
      var signedParam = {
        ...__request.query,
        ...OpenApiUtil.query(t)
      };
      __request.query.Signature = OpenApiUtil.getRPCSignature(signedParam, __request.method, accessKeySecret);
    }
  }
} returns {
  if ((__response.statusCode >= 400) && (__response.statusCode < 600)) {
    var _res = $Stream.readAsJSON(__response.body);
    var err = $object(_res);
    var requestId = $default(err.RequestId, err.requestId);
    var code = $default(err.Code, err.code);
    if ((`${code}` == 'Throttling') || (`${code}` == 'Throttling.User') || (`${code}` == 'Throttling.Api')) {
      throw new Throttling{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        retryAfter =  OpenApiUtil.getThrottlingTimeLeft(__response.headers),
        data = err,
        requestId = `${requestId}`,
      };
    } else if ((__response.statusCode >= 400) && (__response.statusCode < 500)) {
      throw new Client{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        accessDeniedDetail = getAccessDeniedDetail(err),
        requestId = `${requestId}`,
      };
    } else {
      throw new Server{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        requestId = `${requestId}`,
      };
    }
  }
  if (bodyType == 'binary') {
    var resp = {
      body = __response.body,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
    return resp;
  } else if (bodyType == 'byte') {
    var byt = $Stream.readAsBytes(__response.body);
    return {
      body = byt,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'string') {
    var _str = $Stream.readAsString(__response.body);
    return {
      body = _str,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'json'){
    var obj = $Stream.readAsJSON(__response.body);
    var res = $object(obj);
    return {
      body = res,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'array'){
    var arr = $Stream.readAsJSON(__response.body);
    return {
      body = arr,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else {
    return {
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  }
} runtime {
  key = $string($default(runtime.key, @key)),
  cert = $string($default(runtime.cert, @cert)),
  ca = $string($default(runtime.ca, @ca)),
  readTimeout = $number($default(runtime.readTimeout, @readTimeout)),
  connectTimeout = $number($default(runtime.connectTimeout, @connectTimeout)),
  httpProxy = $string($default(runtime.httpProxy, @httpProxy)),
  httpsProxy = $string($default(runtime.httpsProxy, @httpsProxy)),
  noProxy = $string($default(runtime.noProxy, @noProxy)),
  socks5Proxy = $string($default(runtime.socks5Proxy, @socks5Proxy)),
  socks5NetWork = $string($default(runtime.socks5NetWork, @socks5NetWork)),
  maxIdleConns = $number($default(runtime.maxIdleConns, @maxIdleConns)),
  retryOptions = @retryOptions,
  ignoreSSL = runtime.ignoreSSL,
  tlsMinVersion = @tlsMinVersion
}

/**
 * Encapsulate the request and invoke the network
 * @param action api name
 * @param version product version
 * @param protocol http or https
 * @param method e.g. GET
 * @param authType authorization type e.g. AK
 * @param pathname pathname of every api
 * @param bodyType response body type e.g. String
 * @param request object of OpenApiRequest
 * @param runtime which controls some details of call api, such as retry times
 * @return the response
 */
api doROARequest(action: string, version: string, protocol: string, method: string, authType: string, pathname: string, bodyType: string, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): object {
  __request.protocol = $string($default(@protocol, protocol));
  __request.method = method;
  __request.pathname = pathname;
  var globalQueries : map[string]string = {};
  var globalHeaders : map[string]string = {};
  if (!$isNull(@globalParameters)) {
    var globalParams = @globalParameters;
    if (!$isNull(globalParams.queries)) {
      globalQueries = globalParams.queries;
    }
    if (!$isNull(globalParams.headers)) {
      globalHeaders = globalParams.headers;
    }
  }

  var extendsHeaders : map[string]string = {};
  var extendsQueries : map[string]string = {};
  if (!$isNull(runtime.extendsParameters)) {
    var extendsParameters = runtime.extendsParameters;
    if (!$isNull(extendsParameters.headers)) {
      extendsHeaders = extendsParameters.headers;
    }
    if (!$isNull(extendsParameters.queries)) {
      extendsQueries = extendsParameters.queries;
    }
  }

  __request.headers = {
    date = OpenApiUtil.getDateUTCString(),
    host = @endpoint,
    accept = 'application/json',
    x-acs-signature-nonce = OpenApiUtil.getNonce(),
    x-acs-signature-method = 'HMAC-SHA1',
    x-acs-signature-version = '1.0',
    x-acs-version = version,
    x-acs-action = action,
    user-agent = OpenApiUtil.getUserAgent(@userAgent),
    ...globalHeaders,
    ...extendsHeaders,
    ...request.headers
  };

  if (!$isNull(request.body)) {
    __request.body = $JSON.stringify(request.body);
    __request.headers.content-type = 'application/json; charset=utf-8';
  }

  __request.query = {
    ...globalQueries,
    ...extendsQueries,
  };
  if (!$isNull(request.query)) {
    __request.query = {
      ...__request.query,
      ...request.query
    };
  }

  if (authType != 'Anonymous') {
    if ($isNull(@credential)) {
      throw new Client{
        code = `InvalidCredentials`,
        message = `Please set up the credentials correctly. If you are setting them through environment variables, please ensure that ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set correctly. See https://help.aliyun.com/zh/sdk/developer-reference/configure-the-alibaba-cloud-accesskey-environment-variable-on-linux-macos-and-windows-systems for more details.`
      }
    }
    var credentialModel = @credential.getCredential();
    if (!$isNull(credentialModel.providerName)) {
      __request.headers.x-acs-credentials-provider = credentialModel.providerName;
    }
    var credentialType = credentialModel.type;
    if (credentialType == 'bearer') {
      var bearerToken = credentialModel.bearerToken;
      __request.headers.x-acs-bearer-token = bearerToken;
      __request.headers.x-acs-signature-type = 'BEARERTOKEN';
    } else {
      var accessKeyId = credentialModel.accessKeyId;
      var accessKeySecret = credentialModel.accessKeySecret;
      var securityToken = credentialModel.securityToken;
      if (!$isNull(securityToken) && securityToken != "") {
        __request.headers.x-acs-accesskey-id = accessKeyId;
        __request.headers.x-acs-security-token = securityToken;
      }

      var stringToSign = OpenApiUtil.getStringToSign(__request);
      __request.headers.authorization = `acs ${accessKeyId}:${OpenApiUtil.getROASignature(stringToSign, accessKeySecret)}`;
    }
  }
} returns {
  if (__response.statusCode == 204) {
    return {
      headers = __response.headers
    };
  }

  if ((__response.statusCode >= 400) && (__response.statusCode < 600)) {
    var _res = $Stream.readAsJSON(__response.body);
    var err = $object(_res);
    var requestId = $string($default(err.RequestId, err.requestId));
    requestId = $string($default(requestId, err.requestid));
    var code = $string($default(err.Code, err.code));
    if ((`${code}` == 'Throttling') || (`${code}` == 'Throttling.User') || (`${code}` == 'Throttling.Api')) {
      throw new Throttling{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        retryAfter =  OpenApiUtil.getThrottlingTimeLeft(__response.headers),
        data = err,
        requestId = `${requestId}`,
      };
    } else if ((__response.statusCode >= 400) && (__response.statusCode < 500)) {
      throw new Client{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        accessDeniedDetail = getAccessDeniedDetail(err),
        requestId = `${requestId}`,
      };
    } else {
      throw new Server{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        requestId = `${requestId}`,
      };
    }
  }
  if (bodyType == 'binary') {
    var resp = {
      body = __response.body,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
    return resp;
  } else if (bodyType == 'byte') {
    var byt = $Stream.readAsBytes(__response.body);
    return {
      body = byt,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'string') {
    var _str = $Stream.readAsString(__response.body);
    return {
      body = _str,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'json'){
    var obj = $Stream.readAsJSON(__response.body);
    var res = $object(obj);
    return {
      body = res,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'array'){
    var arr = $Stream.readAsJSON(__response.body);
    return {
      body = arr,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else {
    return {
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  }
} runtime {
  key = $string($default(runtime.key, @key)),
  cert = $string($default(runtime.cert, @cert)),
  ca = $string($default(runtime.ca, @ca)),
  readTimeout = $number($default(runtime.readTimeout, @readTimeout)),
  connectTimeout = $number($default(runtime.connectTimeout, @connectTimeout)),
  httpProxy = $string($default(runtime.httpProxy, @httpProxy)),
  httpsProxy = $string($default(runtime.httpsProxy, @httpsProxy)),
  noProxy = $string($default(runtime.noProxy, @noProxy)),
  socks5Proxy = $string($default(runtime.socks5Proxy, @socks5Proxy)),
  socks5NetWork = $string($default(runtime.socks5NetWork, @socks5NetWork)),
  maxIdleConns = $number($default(runtime.maxIdleConns, @maxIdleConns)),
  retryOptions = @retryOptions,
  ignoreSSL = runtime.ignoreSSL,
  tlsMinVersion = @tlsMinVersion
}

/**
 * Encapsulate the request and invoke the network with form body
 * @param action api name
 * @param version product version
 * @param protocol http or https
 * @param method e.g. GET
 * @param authType authorization type e.g. AK
 * @param pathname pathname of every api
 * @param bodyType response body type e.g. String
 * @param request object of OpenApiRequest
 * @param runtime which controls some details of call api, such as retry times
 * @return the response
 */
api doROARequestWithForm(action: string, version: string, protocol: string, method: string,  authType: string, pathname: string, bodyType: string, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): object {
  __request.protocol = $string($default(@protocol, protocol));
  __request.method = method;
  __request.pathname = pathname;
  var globalQueries : map[string]string = {};
  var globalHeaders : map[string]string = {};
  if (!$isNull(@globalParameters)) {
    var globalParams = @globalParameters;
    if (!$isNull(globalParams.queries)) {
      globalQueries = globalParams.queries;
    }
    if (!$isNull(globalParams.headers)) {
      globalHeaders = globalParams.headers;
    }
  }
  var extendsHeaders : map[string]string = {};
  var extendsQueries : map[string]string = {};
  if (!$isNull(runtime.extendsParameters)) {
    var extendsParameters = runtime.extendsParameters;
    if (!$isNull(extendsParameters.headers)) {
      extendsHeaders = extendsParameters.headers;
    }
    if (!$isNull(extendsParameters.queries)) {
      extendsQueries = extendsParameters.queries;
    }
  }
  __request.headers = {
    date = OpenApiUtil.getDateUTCString(),
    host = @endpoint,
    accept = 'application/json',
    x-acs-signature-nonce = OpenApiUtil.getNonce(),
    x-acs-signature-method = 'HMAC-SHA1',
    x-acs-signature-version = '1.0',
    x-acs-version = version,
    x-acs-action = action,
    user-agent = OpenApiUtil.getUserAgent(@userAgent),
    ...globalHeaders,
    ...extendsHeaders,
    ...request.headers
  };

  if (!$isNull(request.body)) {
    var m = $object(request.body);
    __request.body = OpenApiUtil.toForm(m);
    __request.headers.content-type = 'application/x-www-form-urlencoded';
  }


  __request.query = {
    ...globalQueries,
    ...extendsQueries,
  };
  if (!$isNull(request.query)) {
    __request.query = {
      ...__request.query,
      ...request.query
    };
  }

  if (authType != 'Anonymous') {
    if ($isNull(@credential)) {
      throw new Client{
        code = `InvalidCredentials`,
        message = `Please set up the credentials correctly. If you are setting them through environment variables, please ensure that ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set correctly. See https://help.aliyun.com/zh/sdk/developer-reference/configure-the-alibaba-cloud-accesskey-environment-variable-on-linux-macos-and-windows-systems for more details.`
      }
    }
    var credentialModel = @credential.getCredential();
    if (!$isNull(credentialModel.providerName)) {
      __request.headers.x-acs-credentials-provider = credentialModel.providerName;
    }
    var credentialType = credentialModel.type;
    if (credentialType == 'bearer') {
      var bearerToken = credentialModel.bearerToken;
      __request.headers.x-acs-bearer-token = bearerToken;
      __request.headers.x-acs-signature-type = 'BEARERTOKEN';
    } else {
      var accessKeyId = credentialModel.accessKeyId;
      var accessKeySecret = credentialModel.accessKeySecret;
      var securityToken = credentialModel.securityToken;
      if (!$isNull(securityToken) && securityToken != "") {
        __request.headers.x-acs-accesskey-id = accessKeyId;
        __request.headers.x-acs-security-token = securityToken;
      }
      var stringToSign = OpenApiUtil.getStringToSign(__request);
      __request.headers.authorization = `acs ${accessKeyId}:${OpenApiUtil.getROASignature(stringToSign, accessKeySecret)}`;
    }
  }
} returns {
  if (__response.statusCode == 204) {
    return {
      headers = __response.headers
    };
  }

  if ((__response.statusCode >= 400) && (__response.statusCode < 600)) {
    var _res = $Stream.readAsJSON(__response.body);
    var err = $object(_res);
    var requestId = $string($default(err.RequestId, err.requestId));
    var code = $string($default(err.Code, err.code));
    if ((`${code}` == 'Throttling') || (`${code}` == 'Throttling.User') || (`${code}` == 'Throttling.Api')) {
      throw new Throttling{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        retryAfter =  OpenApiUtil.getThrottlingTimeLeft(__response.headers),
        data = err,
        requestId = `${requestId}`,
      };
    } else if ((__response.statusCode >= 400) && (__response.statusCode < 500)) {
      throw new Client{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        accessDeniedDetail = getAccessDeniedDetail(err),
        requestId = `${requestId}`,
      };
    } else {
      throw new Server{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        requestId = `${requestId}`,
      };
    }
  }
  if (bodyType == 'binary') {
    var resp = {
      body = __response.body,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
    return resp;
  } else if (bodyType == 'byte') {
    var byt = $Stream.readAsBytes(__response.body);
    return {
      body = byt,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'string') {
    var _str = $Stream.readAsString(__response.body);
    return {
      body = _str,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'json'){
    var obj = $Stream.readAsJSON(__response.body);
    var res = $object(obj);
    return {
      body = res,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (bodyType == 'array'){
    var arr = $Stream.readAsJSON(__response.body);
    return {
      body = arr,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else {
    return {
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  }
} runtime {
  key = $string($default(runtime.key, @key)),
  cert = $string($default(runtime.cert, @cert)),
  ca = $string($default(runtime.ca, @ca)),
  readTimeout = $number($default(runtime.readTimeout, @readTimeout)),
  connectTimeout = $number($default(runtime.connectTimeout, @connectTimeout)),
  httpProxy = $string($default(runtime.httpProxy, @httpProxy)),
  httpsProxy = $string($default(runtime.httpsProxy, @httpsProxy)),
  noProxy = $string($default(runtime.noProxy, @noProxy)),
  socks5Proxy = $string($default(runtime.socks5Proxy, @socks5Proxy)),
  socks5NetWork = $string($default(runtime.socks5NetWork, @socks5NetWork)),
  maxIdleConns = $number($default(runtime.maxIdleConns, @maxIdleConns)),
  retryOptions = @retryOptions,
  ignoreSSL = runtime.ignoreSSL,
  tlsMinVersion = @tlsMinVersion
}

async function callApi(params: OpenApiUtil.Params, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): object {
  if ($isNull(params)) {
    throw new Client {
      code = 'ParameterMissing',
      message = '\'params\' can not be unset'
    };
  }
  if ($isNull(@signatureVersion) || @signatureVersion != 'v4') {
    if ($isNull(@signatureAlgorithm) || @signatureAlgorithm != 'v2') {
      return doRequest(params, request, runtime);
    } else if ((params.style == 'ROA') && (params.reqBodyType == 'json')) {
      return doROARequest(params.action, params.version, params.protocol, params.method, params.authType, params.pathname, params.bodyType, request, runtime);
    } else if (params.style == 'ROA') {
      return doROARequestWithForm(params.action, params.version, params.protocol, params.method, params.authType, params.pathname, params.bodyType, request, runtime);
    } else {
      return doRPCRequest(params.action, params.version, params.protocol, params.method, params.authType, params.bodyType, request, runtime);
    }
  } else {
    return execute(params, request, runtime);
  }
  
}
/**
 * Encapsulate the request and invoke the network
 * @param action api name
 * @param version product version
 * @param protocol http or https
 * @param method e.g. GET
 * @param authType authorization type e.g. AK
 * @param bodyType response body type e.g. String
 * @param request object of OpenApiRequest
 * @param runtime which controls some details of call api, such as retry times
 * @return the response
 */
api doRequest(params: OpenApiUtil.Params, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): object {
  __request.protocol = $string($default(@protocol, params.protocol));
  __request.method = params.method;
  __request.pathname = params.pathname;
  var globalQueries : map[string]string = {};
  var globalHeaders : map[string]string = {};
  if (!$isNull(@globalParameters)) {
    var globalParams = @globalParameters;
    if (!$isNull(globalParams.queries)) {
      globalQueries = globalParams.queries;
    }
    if (!$isNull(globalParams.headers)) {
      globalHeaders = globalParams.headers;
    }
  }
  var extendsHeaders : map[string]string = {};
  var extendsQueries : map[string]string = {};
  if (!$isNull(runtime.extendsParameters)) {
    var extendsParameters = runtime.extendsParameters;
    if (!$isNull(extendsParameters.headers)) {
      extendsHeaders = extendsParameters.headers;
    }
    if (!$isNull(extendsParameters.queries)) {
      extendsQueries = extendsParameters.queries;
    }
  }
  __request.query = {
    ...globalQueries,
    ...extendsQueries,
    ...request.query,
  };

  // endpoint is setted in product client
  __request.headers = {
    host = @endpoint,
    x-acs-version = params.version,
    x-acs-action = params.action,
    user-agent = OpenApiUtil.getUserAgent(@userAgent),
    x-acs-date= OpenApiUtil.getTimestamp(),
    x-acs-signature-nonce = OpenApiUtil.getNonce(),
    accept = 'application/json',
    ...globalHeaders,
    ...extendsHeaders,
    ...request.headers,
  };
  if (params.style == 'RPC') {
    var headers = getRpcHeaders();
    if (!$isNull(headers)) {
      __request.headers = {
        ...__request.headers,
        ...headers
      };
    }
  }

  var signatureAlgorithm = $string($default(@signatureAlgorithm, 'ACS3-HMAC-SHA256'));
  var hashedRequestPayload = OpenApiUtil.hash($Bytes.from('', 'utf-8'), signatureAlgorithm);

  if (!$isNull(request.stream)) {
    var tmp = $Stream.readAsBytes(request.stream);
    hashedRequestPayload = OpenApiUtil.hash(tmp, signatureAlgorithm);
    __request.body = tmp;
    __request.headers.content-type = 'application/octet-stream';
  } else {
    if (!$isNull(request.body)) {
      if (params.reqBodyType == 'byte') {
        var byteObj = $bytes(request.body);
        hashedRequestPayload = OpenApiUtil.hash(byteObj, signatureAlgorithm);
        __request.body = byteObj;
      } else if (params.reqBodyType == 'json') {
        var jsonObj = $JSON.stringify(request.body);
        hashedRequestPayload = OpenApiUtil.hash(jsonObj.toBytes('utf8'), signatureAlgorithm);
        __request.body = jsonObj;
        __request.headers.content-type = 'application/json; charset=utf-8';
      } else {
        var m = $object(request.body);
        var formObj = OpenApiUtil.toForm(m);
        hashedRequestPayload = OpenApiUtil.hash(formObj.toBytes('utf8'), signatureAlgorithm);
        __request.body = formObj;
        __request.headers.content-type = 'application/x-www-form-urlencoded';
      }
    }
  }

  __request.headers.x-acs-content-sha256 = hashedRequestPayload.toHex();

  if (params.authType != 'Anonymous') {
    if ($isNull(@credential)) {
      throw new Client{
        code = `InvalidCredentials`,
        message = `Please set up the credentials correctly. If you are setting them through environment variables, please ensure that ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set correctly. See https://help.aliyun.com/zh/sdk/developer-reference/configure-the-alibaba-cloud-accesskey-environment-variable-on-linux-macos-and-windows-systems for more details.`
      }
    }
    var credentialModel = @credential.getCredential();
    if (!$isNull(credentialModel.providerName)) {
      __request.headers.x-acs-credentials-provider = credentialModel.providerName;
    }
    var authType = credentialModel.type;
    if (authType == 'bearer') {
      var bearerToken = credentialModel.bearerToken;
      __request.headers.x-acs-bearer-token = bearerToken;
      if (params.style == 'RPC') {
        __request.query.SignatureType = 'BEARERTOKEN';
      } else {
        __request.headers.x-acs-signature-type = 'BEARERTOKEN';
      }
    } else {
      var accessKeyId = credentialModel.accessKeyId;
      var accessKeySecret = credentialModel.accessKeySecret;
      var securityToken = credentialModel.securityToken;

      if (!$isNull(securityToken) && securityToken != "") {
        __request.headers.x-acs-accesskey-id = accessKeyId;
        __request.headers.x-acs-security-token = securityToken;
      }
      __request.headers.Authorization = OpenApiUtil.getAuthorization(__request, signatureAlgorithm, hashedRequestPayload.toHex(), accessKeyId, accessKeySecret);
    }
  }
} returns {
  if ((__response.statusCode >= 400) && (__response.statusCode < 600)) {
    var err : map[string]any = {};
    if (!$isNull(__response.headers.content-type) && __response.headers.content-type == 'text/xml;charset=utf-8') {
      var _str = $Stream.readAsString(__response.body);
      var respMap = $XML.parseXml(_str, null);
      err = $object(respMap.Error);
    } else {
      var _res = $Stream.readAsJSON(__response.body);
      err = $object(_res);
    }
    var requestId = $string($default(err.RequestId, err.requestId));
    var code = $string($default(err.Code, err.code));
    if ((`${code}` == 'Throttling') || (`${code}` == 'Throttling.User') || (`${code}` == 'Throttling.Api')) {
      throw new Throttling{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        retryAfter =  OpenApiUtil.getThrottlingTimeLeft(__response.headers),
        data = err,
        requestId = `${requestId}`,
      };
    } else if ((__response.statusCode >= 400) && (__response.statusCode < 500)) {
      throw new Client{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        accessDeniedDetail = getAccessDeniedDetail(err),
        requestId = `${requestId}`,
      };
    } else {
      throw new Server{
        statusCode = __response.statusCode,
        code = `${code}`,
        message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${requestId}`,
        description = `${$default(err.Description, err.description)}`,
        data = err,
        requestId = `${requestId}`,
      };
    }
  }
  if (params.bodyType == 'binary') {
    var resp = {
      body = __response.body,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
    return resp;
  } else if (params.bodyType == 'byte') {
    var byt = $Stream.readAsBytes(__response.body);
    return {
      body = byt,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (params.bodyType == 'string') {
    var respStr = $Stream.readAsString(__response.body);
    return {
      body = respStr,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (params.bodyType == 'json'){
    var obj = $Stream.readAsJSON(__response.body);
    var res = $object(obj);
    return {
      body = res,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else if (params.bodyType == 'array'){
    var arr = $Stream.readAsJSON(__response.body);
    return {
      body = arr,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  } else {
    var anything = $Stream.readAsString(__response.body);
    return {
      body = anything,
      headers = __response.headers,
      statusCode = __response.statusCode
    };
  }
} runtime {
  key = $string($default(runtime.key, @key)),
  cert = $string($default(runtime.cert, @cert)),
  ca = $string($default(runtime.ca, @ca)),
  readTimeout = $number($default(runtime.readTimeout, @readTimeout)),
  connectTimeout = $number($default(runtime.connectTimeout, @connectTimeout)),
  httpProxy = $string($default(runtime.httpProxy, @httpProxy)),
  httpsProxy = $string($default(runtime.httpsProxy, @httpsProxy)),
  noProxy = $string($default(runtime.noProxy, @noProxy)),
  socks5Proxy = $string($default(runtime.socks5Proxy, @socks5Proxy)),
  socks5NetWork = $string($default(runtime.socks5NetWork, @socks5NetWork)),
  maxIdleConns = $number($default(runtime.maxIdleConns, @maxIdleConns)),
  retryOptions = @retryOptions,
  ignoreSSL = runtime.ignoreSSL,
  tlsMinVersion = @tlsMinVersion
}


/**
 * Encapsulate the request and invoke the network
 * @param action api name
 * @param version product version
 * @param protocol http or https
 * @param method e.g. GET
 * @param authType authorization type e.g. AK
 * @param bodyType response body type e.g. String
 * @param request object of OpenApiRequest
 * @param runtime which controls some details of call api, such as retry times
 * @return the response
 */
api execute(params: OpenApiUtil.Params, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): object {
  // spi = new Gateway();//Gateway implements SPI，这一步在产品 SDK 中实例化
  var headers = getRpcHeaders();
  var globalQueries : map[string]string = {};
  var globalHeaders : map[string]string = {};
  if (!$isNull(@globalParameters)) {
    var globalParams = @globalParameters;
    if (!$isNull(globalParams.queries)) {
      globalQueries = globalParams.queries;
    }
    if (!$isNull(globalParams.headers)) {
      globalHeaders = globalParams.headers;
    }
  }
  var extendsHeaders : map[string]string = {};
  var extendsQueries : map[string]string = {};
  if (!$isNull(runtime.extendsParameters)) {
    var extendsParameters = runtime.extendsParameters;
    if (!$isNull(extendsParameters.headers)) {
      extendsHeaders = extendsParameters.headers;
    }
    if (!$isNull(extendsParameters.queries)) {
      extendsQueries = extendsParameters.queries;
    }
  }
  var requestContext = new SPI.InterceptorContext.request{
    headers = {
      ...globalHeaders,
      ...extendsHeaders,
      ...request.headers,
      ...headers
    },
    query = {
      ...globalQueries,
      ...extendsQueries,
      ...request.query,
    },
    body = request.body,
    stream = request.stream,
    hostMap = request.hostMap,
    pathname = params.pathname,
    productId = @productId,
    action = params.action,
    version = params.version,
    protocol = $string($default(@protocol, params.protocol)),
    method = $string($default(@method, params.method)),
    authType = params.authType,
    bodyType = params.bodyType,
    reqBodyType = params.reqBodyType,
    style = params.style,
    credential = @credential,
    signatureVersion = @signatureVersion,
    signatureAlgorithm = @signatureAlgorithm,
    userAgent = OpenApiUtil.getUserAgent(@userAgent)
  };
  var configurationContext = new SPI.InterceptorContext.configuration{
    regionId = @regionId,
    endpoint = $string($default(request.endpointOverride, @endpoint)),
    endpointRule = @endpointRule,
    endpointMap = @endpointMap,
    endpointType = @endpointType,
    network = @network,
    suffix = @suffix
  };
  var interceptorContext =  new SPI.InterceptorContext{
    request = requestContext,
    configuration = configurationContext
  };
  var attributeMap = new SPI.AttributeMap{};

  // 1. spi.modifyConfiguration(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap);
  @spi.modifyConfiguration(interceptorContext, attributeMap);

  // 2. spi.modifyRequest(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap);
  @spi.modifyRequest(interceptorContext, attributeMap);

  __request.protocol = interceptorContext.request.protocol;
  __request.method = interceptorContext.request.method;
  __request.pathname = interceptorContext.request.pathname;
  __request.query = interceptorContext.request.query;
  __request.body = interceptorContext.request.stream;
  __request.headers = interceptorContext.request.headers;
  
} returns {
  var responseContext = new SPI.InterceptorContext.response{
    statusCode = __response.statusCode,
    headers = __response.headers,
    body = __response.body
  };
  interceptorContext.response = responseContext;

  // 3. spi.modifyResponse(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap);
  @spi.modifyResponse(interceptorContext, attributeMap);

  return {
    headers = interceptorContext.response.headers,
    statusCode = interceptorContext.response.statusCode,
    body = interceptorContext.response.deserializedBody
  };

} runtime {
  key = $string($default(runtime.key, @key)),
  cert = $string($default(runtime.cert, @cert)),
  ca = $string($default(runtime.ca, @ca)),
  readTimeout = $number($default(runtime.readTimeout, @readTimeout)),
  connectTimeout = $number($default(runtime.connectTimeout, @connectTimeout)),
  httpProxy = $string($default(runtime.httpProxy, @httpProxy)),
  httpsProxy = $string($default(runtime.httpsProxy, @httpsProxy)),
  noProxy = $string($default(runtime.noProxy, @noProxy)),
  socks5Proxy = $string($default(runtime.socks5Proxy, @socks5Proxy)),
  socks5NetWork = $string($default(runtime.socks5NetWork, @socks5NetWork)),
  maxIdleConns = $number($default(runtime.maxIdleConns, @maxIdleConns)),
  retryOptions = @retryOptions,
  ignoreSSL = runtime.ignoreSSL,
  tlsMinVersion = @tlsMinVersion,
  disableHttp2 = $boolean($default(@disableHttp2, false))
}

@sse(true)
api callSSEApi(params: OpenApiUtil.Params, request: OpenApiUtil.OpenApiRequest, runtime: $RuntimeOptions): asyncIterator[SSEResponse] {
  __request.protocol = $string($default(@protocol, params.protocol));
  __request.method = params.method;
  __request.pathname = params.pathname;
  var globalQueries : map[string]string = {};
  var globalHeaders : map[string]string = {};
  if (!$isNull(@globalParameters)) {
    var globalParams = @globalParameters;
    if (!$isNull(globalParams.queries)) {
      globalQueries = globalParams.queries;
    }
    if (!$isNull(globalParams.headers)) {
      globalHeaders = globalParams.headers;
    }
  }
  var extendsHeaders : map[string]string = {};
  var extendsQueries : map[string]string = {};
  if (!$isNull(runtime.extendsParameters)) {
    var extendsParameters = runtime.extendsParameters;
    if (!$isNull(extendsParameters.headers)) {
      extendsHeaders = extendsParameters.headers;
    }
    if (!$isNull(extendsParameters.queries)) {
      extendsQueries = extendsParameters.queries;
    }
  }
  __request.query = {
    ...globalQueries,
    ...extendsQueries,
    ...request.query,
  };

  // endpoint is setted in product client
  __request.headers = {
    host = @endpoint,
    x-acs-version = params.version,
    x-acs-action = params.action,
    user-agent = OpenApiUtil.getUserAgent(@userAgent),
    x-acs-date= OpenApiUtil.getTimestamp(),
    x-acs-signature-nonce = OpenApiUtil.getNonce(),
    accept = 'application/json',
    ...extendsHeaders,
    ...globalHeaders,
    ...request.headers,
  };
  if (params.style == 'RPC') {
    var headers = getRpcHeaders();
    if (!$isNull(headers)) {
      __request.headers = {
        ...__request.headers,
        ...headers
      };
    }
  }

  var signatureAlgorithm = $string($default(@signatureAlgorithm, 'ACS3-HMAC-SHA256'));
  var hashedRequestPayload = OpenApiUtil.hash($Bytes.from('', 'utf-8'), signatureAlgorithm);

  if (!$isNull(request.stream)) {
    var tmp = $Stream.readAsBytes(request.stream);
    hashedRequestPayload = OpenApiUtil.hash(tmp, signatureAlgorithm);
    __request.body = tmp;
    __request.headers.content-type = 'application/octet-stream';
  } else {
    if (!$isNull(request.body)) {
      if (params.reqBodyType == 'byte') {
        var byteObj = $bytes(request.body);
        hashedRequestPayload = OpenApiUtil.hash(byteObj, signatureAlgorithm);
        __request.body = byteObj;
      } else if (params.reqBodyType == 'json') {
        var jsonObj = $JSON.stringify(request.body);
        hashedRequestPayload = OpenApiUtil.hash(jsonObj.toBytes('utf8'), signatureAlgorithm);
        __request.body = jsonObj;
        __request.headers.content-type = 'application/json; charset=utf-8';
      } else {
        var m = $object(request.body);
        var formObj = OpenApiUtil.toForm(m);
        hashedRequestPayload = OpenApiUtil.hash(formObj.toBytes('utf8'), signatureAlgorithm);
        __request.body = formObj;
        __request.headers.content-type = 'application/x-www-form-urlencoded';
      }
    }
  }

  __request.headers.x-acs-content-sha256 = hashedRequestPayload.toHex();

  if (params.authType != 'Anonymous') {
    var credentialModel = @credential.getCredential();
    if (!$isNull(credentialModel.providerName)) {
      __request.headers.x-acs-credentials-provider = credentialModel.providerName;
    }
    var authType = credentialModel.type;
    if (authType == 'bearer') {
      var bearerToken = credentialModel.bearerToken;
      __request.headers.x-acs-bearer-token = bearerToken;
    } else {
      var accessKeyId = credentialModel.accessKeyId;
      var accessKeySecret = credentialModel.accessKeySecret;
      var securityToken = credentialModel.securityToken;

      if (!$isNull(securityToken) && securityToken != "") {
        __request.headers.x-acs-accesskey-id = accessKeyId;
        __request.headers.x-acs-security-token = securityToken;
      }
      __request.headers.Authorization = OpenApiUtil.getAuthorization(__request, signatureAlgorithm, hashedRequestPayload.toHex(), accessKeyId, accessKeySecret);
    }
  }
} returns {
  if ((__response.statusCode >= 400) && (__response.statusCode < 600)) {
    var err : map[string]any = {};
    if (!$isNull(__response.headers.content-type) && __response.headers.content-type == 'text/xml;charset=utf-8') {
      var _str = $Stream.readAsString(__response.body);
      var respMap = $XML.parseXml(_str, null);
      err = $object(respMap.Error);
    } else {
      var _res = $Stream.readAsJSON(__response.body);
      err = $object(_res);
    }
    err.statusCode = __response.statusCode;
    throw {
      code = `${$default(err.Code, err.code)}`,
      message = `code: ${__response.statusCode}, ${$default(err.Message, err.message)} request id: ${$default(err.RequestId, err.requestId)}`,
      data = err,
      description = `${$default(err.Description, err.description)}`,
      accessDeniedDetail = $default(err.AccessDeniedDetail, err.accessDeniedDetail),
    };
  }
  var events = $Stream.readAsSSE(__response.body);
  for(var event : events) {
    yield new SSEResponse{
      statusCode = __response.statusCode,
      headers = __response.headers,
      event = event,
    };
  }
  return null;
} runtime {
  key = $string($default(runtime.key, @key)),
  cert = $string($default(runtime.cert, @cert)),
  ca = $string($default(runtime.ca, @ca)),
  readTimeout = $number($default(runtime.readTimeout, @readTimeout)),
  connectTimeout = $number($default(runtime.connectTimeout, @connectTimeout)),
  httpProxy = $string($default(runtime.httpProxy, @httpProxy)),
  httpsProxy = $string($default(runtime.httpsProxy, @httpsProxy)),
  noProxy = $string($default(runtime.noProxy, @noProxy)),
  socks5Proxy = $string($default(runtime.socks5Proxy, @socks5Proxy)),
  socks5NetWork = $string($default(runtime.socks5NetWork, @socks5NetWork)),
  maxIdleConns = $number($default(runtime.maxIdleConns, @maxIdleConns)),
  retryOptions = @retryOptions,
  ignoreSSL = runtime.ignoreSSL,
  tlsMinVersion = @tlsMinVersion
}

/**
 * Get accesskey id by using credential
 * @return accesskey id
 */
async function getAccessKeyId(): string {
  if ($isNull(@credential)) {
    return '';
  }
  var accessKeyId = @credential.getAccessKeyId();
  return accessKeyId;
}

/**
 * Get accesskey secret by using credential
 * @return accesskey secret
 */
async function getAccessKeySecret(): string {
  if ($isNull(@credential)) {
    return '';
  }
  var secret = @credential.getAccessKeySecret();
  return secret;
}

/**
 * Get security token by using credential
 * @return security token
 */
async function getSecurityToken(): string {
  if ($isNull(@credential)) {
    return '';
  }
  var token = @credential.getSecurityToken();
  return token;
}

/**
 * Get bearer token by credential
 * @return bearer token
 */
async function getBearerToken(): string {
  if ($isNull(@credential)) {
    return '';
  }
  var token = @credential.getBearerToken();
  return token;
}

/**
 * Get credential type by credential
 * @return credential type e.g. access_key
 */
async function getType(): string {
  if ($isNull(@credential)) {
    return '';
  }
  var authType = @credential.getType();
  return authType;
}

/**
 * If the endpointRule and config.endpoint are empty, throw error
 * @param config config contains the necessary information to create a client
 */
function checkConfig(config: OpenApiUtil.Config)throws : void {
  if ($isNull(@endpointRule) && $isNull(config.endpoint)) {
    throw new Client {
      code = 'ParameterMissing',
      message = '\'config.endpoint\' can not be empty'
    };
  }
}

/**
 * set gateway client
 * @param spi.
 */
function setGatewayClient(spi: SPI)throws : void {
  @spi = spi;
}

/**
 * set RPC header for debug
 * @param headers headers for debug, this header can be used only once.
 */
function setRpcHeaders(headers: map[string] string)throws : void {
  @headers = headers;
}

/**
 * get RPC header for debug
 */
function getRpcHeaders() throws : map[string] string {
  var headers: map[string] string = @headers;
  @headers = null;
  return headers;
}

function getAccessDeniedDetail(err: map[string] any): map[string] any {
  var accessDeniedDetail : map[string] any = null;
  if (!$isNull(err.AccessDeniedDetail)) {
    var detail1 = $object(err.AccessDeniedDetail);
    accessDeniedDetail = detail1;
  } else if (!$isNull(err.accessDeniedDetail)) {
    var detail2 = $object(err.accessDeniedDetail);
    accessDeniedDetail = detail2;
  }
  return accessDeniedDetail;
}
